package com.guanzi.activiti.controller;

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.guanzi.activiti.utils.R;
import com.guanzi.activiti.utils.SecurityUtil;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;

/**
 * @author 管子
 * @date 2025/2/9 9:15
 * @description: ActivitiController 类
 */
@Slf4j
@RequestMapping("/activiti")
@RestController
public class ActivitiController {

    // 提供对流程定义和部署存储库的访问服务
    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private SecurityUtil securityUtil;

    /**
     * 部署流程
     * 1、设计器设计流程xml/png
     * 2、部署流程
     * 3、发起流程
     * 4、执行流程
     * @param file 流程zip压缩包
     */
    @PostMapping("/deploy")
    public R<Deployment> deploy(@RequestPart("file") MultipartFile file) {
        try {
            if (file.isEmpty()) {
                throw new NullPointerException("部署压缩包不能为空!");
            }
            DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
            // 压缩流
            ZipInputStream zip = new ZipInputStream(file.getInputStream());
            deploymentBuilder.addZipInputStream(zip);
            // 设置部署流程名称
            deploymentBuilder.name("请假审批");
            // 部署流程
            Deployment deploy = deploymentBuilder.deploy();
            return R.success(deploy);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error(e.getMessage());
        }
    }

    /**
     * 查询流程部署信息
     * @return
     */
    @PostMapping("/queryDeploymentInfo")
    public R<String> queryDeploymentInfo() {
        List<Deployment> list = repositoryService.createDeploymentQuery().list();
        log.info("流程部署信息: {}", list);
        return R.success(list.toString());
    }

    /**
     * 查询流程定义信息
     * @return
     */
    @PostMapping("/queryProcessInfo")
    public R<String> queryProcessInfo() {
        List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();
        log.info("流程定义信息: {}", list);
        return R.success(list.toString());
    }

    /**
     * 根据部署id删除流程部署
     * @return
     */
    @GetMapping("/deleteDeploymentById")
    public R<Boolean> deleteDeploymentById(@RequestParam String deploymentId) {
        Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();
        if (ObjectUtils.isNotEmpty(deployment)) {
            repositoryService.deleteDeployment(deploymentId);
        }
        return R.success(true);
    }

    /**
     * 发起流程
     * @param processDefinitionId
     * @return
     */
    @GetMapping("/startProcess")
    public R<Boolean> startProcess(@RequestParam String processDefinitionId) {
        log.info("发起流程, processDefinitionId: {}", processDefinitionId);
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
        if (ObjectUtils.isEmpty(processDefinition)) {
            throw new NullPointerException("流程定义为空!");
        }

        // 流程节点中变量
        Map<String, Object> variables = new HashMap<>();
        variables.put("userName", "管子经理");
        // test05
//        variables.put("day", "8");
        // test06
        variables.put("day", "3");
        ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinitionId, variables);
        log.info("流程实例: {}", processInstance);
        return R.success(true);
    }

    /**
     * 完成任务
     * @param processInstanceId 流程实例ID
     * @return
     */
    @GetMapping("/completeTask")
    public R<Boolean> completeTask(@RequestParam String processInstanceId) {
        List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        if (taskList.size() != 1) {
            return R.error("任务列表为空!");
        }
        log.info("任务列表: {}", taskList);

        // 根据任务ID，完成任务
        taskService.complete(taskList.get(0).getId());
        return R.success(true);
    }

    /**
     * 查询历史流程实例
     */
    @GetMapping("/queryHistoryProcessInstance")
    public R<String> queryHistoryProcessInstance() {
        List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery().list();
        log.info("查询历史流程实例: {}", list);
        return R.success(list.toString());
    }


    /**
     * 查询历史任务
     * @return
     */
    @GetMapping("/queryHistoryTask")
    public R<String> queryHistoryTask() {
        List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery().list();
        log.info("查询历史任务: {}", list);

        StringBuilder sb = new StringBuilder();
        list.forEach(item -> sb.append(item.toString()).append("\n"));
        return R.success(sb.toString());
    }

    /**
     * 查询历史活动流程实例
     */
    @GetMapping("/queryHistoryActivityInstance")
    public R<String> queryHistoryActivityInstance() {
        List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery().list();
        log.info("查询历史活动流程实例: {}", list);
        return R.success(list.toString());
    }

    /**
     * 根据代办人查询任务
     */
    @GetMapping("/queryTaskByAssignee")
    public R<String> queryTaskByAssignee(@RequestParam String assignee) {
        List<Task> list = taskService.createTaskQuery().taskAssignee(assignee).active().list();
        log.info("根据代办人查询任务: {}", list);
        return R.success(list.toString());
    }

    /**
     * 按任务id更新代办人
     */
    @GetMapping("/updateAssigneeByTaskId")
    public R<String> updateAssigneeByTaskId(@RequestParam String taskId,
                                            @RequestParam String assignee) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (ObjectUtils.isNotEmpty(task)) {
            taskService.setAssignee(taskId, assignee);
        }
        return R.success("更新代办人成功!");
    }

    /**
     * 添加审批人意见
     */
    @GetMapping("/addComment")
    public R<String> addComment(@RequestParam String taskId,
                                @RequestParam String processInstanceId,
                                @RequestParam String message) {
        Task task = taskService.createTaskQuery().taskId(taskId).processInstanceId(processInstanceId).singleResult();
        if (ObjectUtils.isEmpty(task)) {
            return R.error("任务为空!");
        }
        // processInstanceId 和 message 参数之间还可以放一个自定义参数，可以放用户ID
        taskService.addComment(taskId, processInstanceId, message);
        return R.success("添加审批人意见成功!");
    }

    /**
     * 查询个人审批意见
     */
    @GetMapping("/queryComment")
    public R<String> queryCommentByTaskId(@RequestParam String taskId) {
        List<Comment> list = taskService.getTaskComments(taskId);
        StringBuilder sb = new StringBuilder();
        list.forEach(item -> {
            sb.append(item.toString()).append("\n");
        });
        return R.success(sb.toString());
    }

    /**
     * 查询候选人任务
     * @param userName
     * @return
     */
    @GetMapping("queryTaskByCandidateUser")
    public R<String> queryTaskByCandidateUser(@RequestParam String userName){
        securityUtil.logInAs(userName);
        List<Task> taskList = taskService.createTaskQuery()
                //候选人名称
                .taskCandidateUser(userName)
                .list();
        return R.success(taskList.toString());
    }

    /**
     * 拾取任务，拾取后的任务才能被候选人完成
     */
    @GetMapping("/claimTask")
    public R<String> claimTask(@RequestParam String taskId,
                              @RequestParam String userName) {
        securityUtil.logInAs(userName);

        Task task = taskService.createTaskQuery()
                .taskId(taskId)
                .taskCandidateUser(userName)
                .singleResult();
        if (ObjectUtils.isEmpty(task)) {
            return R.error("任务为空!");
        }

        taskService.claim(taskId, userName);
        return R.success("拾取任务成功!");
    }

}
